package com.mrlong.mlcamerac

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.ImageFormat
import android.graphics.SurfaceTexture
import android.hardware.camera2.*
import android.media.ImageReader
import android.os.Bundle
import android.os.Handler
import android.os.HandlerThread
import android.support.v4.app.ActivityCompat
import android.support.v7.app.AppCompatActivity
import android.util.Log
import android.util.Size
import android.view.Surface
import android.view.TextureView
import android.widget.Button
import com.mrlong.mlcamerac.push.Encoder
import com.mrlong.mlcamerac.push.PushConnectListenr
import java.nio.ByteBuffer


/**
 * Camera2 API调用基础流程：
 *1、通过context.getSystemService(Context.CAMERA_SERVICE) 获取CameraManager；
 *2、调用CameraManager .open()方法在回调中得到CameraDevice；
 *3、通过CameraDevice.createCaptureSession() 在回调中获取CameraCaptureSession；
 *4、构建CaptureRequest, 有三种模式可选 预览/拍照/录像.；
 *5、通过 CameraCaptureSession发送CaptureRequest, capture表示只发一次请求, setRepeatingRequest表示不断发送请求；
 *6、拍照数据可以在ImageReader.OnImageAvailableListener回调中获取, CaptureCallback中则可获取拍照实际的参数和Camera当前状态
 */
class Camera2TextureViewActivity : AppCompatActivity(), TextureView.SurfaceTextureListener,
    ImageReader.OnImageAvailableListener {
    private val TAG = "测试"
    var handler: Handler? = null
    private val mImageWidth = 640
    private val mImageHeight = 480
    private var textureView: TextureView? = null
    private var mPreviewSize: Size? = null
    private var mCamera: CameraDevice? = null
    private var mPreviewBuilder: CaptureRequest.Builder? = null
    private var mCameraID = "1"
    private var changeButton: Button? = null
    private var startPush: Button? = null
    private val mCameraDeviceStateCallBack: CameraDevice.StateCallback =
        object : CameraDevice.StateCallback() {
            override fun onOpened(camera: CameraDevice) {
                mCamera = camera
                startPreview(camera)
            }

            override fun onDisconnected(camera: CameraDevice) {
            }

            override fun onError(camera: CameraDevice, error: Int) {
            }
        }
    private val mSessionStateCallback = object : CameraCaptureSession.StateCallback() {
        override fun onConfigured(session: CameraCaptureSession) {
            updatePreview(session)
        }

        override fun onConfigureFailed(session: CameraCaptureSession) {
        }

    }

    private fun updatePreview(session: CameraCaptureSession) {
        try {
            session.setRepeatingRequest(mPreviewBuilder!!.build(), null, handler)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    var imageReader: ImageReader? = null
    private fun startPreview(mCamera: CameraDevice) {
        val texture = textureView?.surfaceTexture
        //预览尺寸
        texture?.setDefaultBufferSize(mPreviewSize!!.width, mPreviewSize!!.height)
        val surface = Surface(texture)
        try {
            mPreviewBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW)

            //这里是推流尺寸
            imageReader =
                ImageReader.newInstance(mImageWidth, mImageHeight, ImageFormat.YUV_420_888, 1)
            imageReader?.setOnImageAvailableListener(this, handler)
            //这里不添加surface 也能拿到流
            mPreviewBuilder?.addTarget(surface)
            mPreviewBuilder?.addTarget(imageReader!!.surface)

            mCamera.createCaptureSession(
                listOf(surface, imageReader?.surface),
                mSessionStateCallback,
                handler
            )
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_camera2_texture_view)
        initView()
        initLooper()
        startService(Intent(this, MainService::class.java))
    }

    private fun initView() {
        textureView = findViewById<TextureView>(R.id.textureView)
        changeButton = findViewById<Button>(R.id.changeCameraID)
        startPush = findViewById<Button>(R.id.startPush)
        changeButton?.setOnClickListener {
            openCamera()
        }
        startPush?.setOnClickListener {
            startPushAction()
        }
        textureView?.surfaceTextureListener = this
    }

    var encoder: Encoder? = null
    var framerate = 15
    var biterate = 50 * 1000
    private fun startPushAction() {
        encoder = Encoder
            .getInstance();
        encoder?.init(
            this,
            "rtmp://114.251.58.182:1935/live/54321",
            mImageWidth,
            mImageHeight,
            framerate, biterate,
            object : PushConnectListenr {
                override fun onConnecting() {
                    showMessage("连接中")
                }

                override fun onConnectSuccess() {
                    showMessage("连接成功")
                }

                override fun onConnectFail(msg: String?) {
                    showMessage("连接失败")
                }
            }
        )
        encoder?.setCamera("1")
        encoder?.start()
    }

    fun showMessage(message: String) {
        Log.e("=====>", "$message")
    }

    override fun onDestroy() {
        super.onDestroy()
        encoder?.stop()
        mCamera?.close()
        mCamera = null;
        handler = null;
    }

    private fun initLooper() {
        val handlerThread = HandlerThread("Camera222")
        handlerThread.start()
        handler = Handler(handlerThread.looper)
    }

    override fun onSurfaceTextureAvailable(surface: SurfaceTexture, width: Int, height: Int) {
        openCamera()
    }


    override fun onSurfaceTextureSizeChanged(surface: SurfaceTexture, width: Int, height: Int) {
    }

    override fun onSurfaceTextureDestroyed(surface: SurfaceTexture): Boolean {
        return false
    }

    override fun onSurfaceTextureUpdated(surface: SurfaceTexture) {
    }

    override fun onImageAvailable(reader: ImageReader?) {
        try {
            val image = imageReader!!.acquireLatestImage() ?: return
            val planes = image.planes
            if (planes.size >= 3) {
                val bufferY: ByteBuffer = planes[0].buffer
                val bufferU: ByteBuffer = planes[1].buffer
                val bufferV: ByteBuffer = planes[2].buffer
                val lengthY: Int = bufferY.remaining()
                val lengthU: Int = bufferU.remaining()
                val lengthV: Int = bufferV.remaining()
                val dataYUV = ByteArray(lengthY + lengthU + lengthV)
                bufferY.get(dataYUV, 0, lengthY)
                bufferU.get(dataYUV, lengthY, lengthU)
                bufferV.get(dataYUV, lengthY + lengthU, lengthV)
                Encoder.getInstance().putYUVData(dataYUV)
            }
            image?.close()
        } catch (ex: Exception) {
        } finally {

        }
    }

    private fun openCamera() {
        try {
            val cameraManager = getSystemService(CAMERA_SERVICE) as CameraManager

            //选择相机
            val cameraIdList = cameraManager.cameraIdList
            run breaking@{
                for (id in cameraIdList) {
                    if (mCameraID == CameraCharacteristics.LENS_FACING_BACK.toString()) {
                        mCameraID = CameraCharacteristics.LENS_FACING_FRONT.toString();
                        mCamera?.close()
                        return@breaking
                    } else if (mCameraID == CameraCharacteristics.LENS_FACING_FRONT.toString()) {
                        mCameraID = CameraCharacteristics.LENS_FACING_BACK.toString()
                        mCamera?.close()
                        return@breaking
                    }
                }
            }

            //获取相机的支持参数
            val cameraCharacteristics =
                cameraManager.getCameraCharacteristics(mCameraID) as CameraCharacteristics
            val map =
                cameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
            mPreviewSize = map?.getOutputSizes(SurfaceTexture::class.java)?.get(0) as Size
            if (ActivityCompat.checkSelfPermission(
                    this,
                    Manifest.permission.CAMERA
                ) != PackageManager.PERMISSION_GRANTED
            ) {
                return
            }

            if ("1" == mCameraID) {
                encoder?.setCamera("1")
            } else if ("0" == mCameraID) {
                encoder?.setCamera("0")
            }
            cameraManager.openCamera(mCameraID, mCameraDeviceStateCallBack, handler)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


}